package cn.org.xwb.bookmall.admin.controller;

import cn.org.xwb.bookmall.admin.annotation.IsLoginObj;
import cn.org.xwb.bookmall.admin.annotation.IsLoginParam;
import cn.org.xwb.bookmall.admin.service.AdminProductService;
import cn.org.xwb.bookmall.admin.utils.Convert2PoUtil;
import cn.org.xwb.bookmall.admin.vo.UploadProductVo;
import cn.org.xwb.bookmall.model.constant.AccountConst;
import cn.org.xwb.bookmall.model.constant.ManagerConst;
import cn.org.xwb.bookmall.model.po.ProductCategory;
import cn.org.xwb.bookmall.model.po.ProductCategorySub;
import cn.org.xwb.bookmall.model.po.ProductOptions;
import cn.org.xwb.bookmall.model.po.ProductParam;
import cn.org.xwb.bookmall.model.service.impl.CommentsServiceImpl;
import cn.org.xwb.bookmall.model.vo.CommentsVo;
import cn.org.xwb.bookmall.model.vo.ProductConditionVo;
import cn.org.xwb.common.encrypt.annotation.des.DesEn;
import cn.org.xwb.common.encrypt.annotation.rsa.RsaDeParam;
import cn.org.xwb.common.encrypt.constant.EncryptConstant;
import cn.org.xwb.common.encrypt.dto.RsaKeyPair;
import cn.org.xwb.common.encrypt.utils.DecryptUtil;
import cn.org.xwb.common.utils.ObjUtilWithAspect;
import cn.org.xwb.bookmall.model.vo.ProductCategoryVo;
import cn.org.xwb.common.encrypt.annotation.rsa.RsaDe;
import cn.org.xwb.common.encrypt.annotation.rsa.RsaDeObj;
import cn.org.xwb.common.error.annotation.ServerErrorCatch;
import cn.org.xwb.common.model.vo.RespResult;
import cn.org.xwb.common.valid.annotation.nu.NotNull;
import cn.org.xwb.common.valid.annotation.nu.NotNullObj;
import cn.org.xwb.common.valid.annotation.nu.NotNullParam;
import cn.org.xwb.common.valid.annotation.str.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/product")
public class AdminProductController {

    @Autowired
    private AdminProductService adminProductService;

    @Autowired
    private ObjUtilWithAspect objUtilWithAspect;

    @Autowired
    private RsaKeyPair rsaKeyPair;

    /**
     * 获取所有商品分类，包括二级商品分类
     *
     * @return
     */
    @GetMapping("/category/all")
    @ServerErrorCatch
    @StrNotNull
    @RsaDe
    @IsLoginParam
    @DesEn
    public RespResult<Object> getAllProductCategory(
            @RequestParam(AccountConst.ACCOUNT_PARAM_NAME)
            @StrNotNullParam @RsaDeParam
            String account,
            @RequestParam(EncryptConstant.DES_KEY_PARAM_NAME)
            @StrNotNullParam @RsaDeParam
            String desKey
    ) {
        return adminProductService.getProductCategoryAll();
    }

    @GetMapping("/category/page")
    @ServerErrorCatch
    @StrNotNull
    @RsaDe
    @StrMaxLen
    @IsLoginParam
    @DesEn
    public RespResult<Object> getProductCategoryPage(
            @RequestParam(AccountConst.ACCOUNT_PARAM_NAME)
            @StrNotNullParam @RsaDeParam
            String account,
            @RequestParam(EncryptConstant.DES_KEY_PARAM_NAME)
            @StrNotNullParam @RsaDeParam
            String desKey,
            @RequestParam("current")
            Integer current,
            @RequestParam("pageSize")
            Integer pageSize,
            @RequestParam(value = "disabled", required = false)
            Boolean disabled,
            @RequestParam(value = "nameMatch", required = false)
            @RsaDeParam @StrMaxLenParam(ManagerConst.AUTHORITY_NAME_MAX_LEN)
            String nameMatch,
            @RequestParam(value = "codeMatch", required = false)
            @RsaDeParam @StrMaxLenParam(ManagerConst.AUTHORITY_CODE_MAX_LEN)
            String codeMatch
    ) {
        return adminProductService.getProductCategoryPage(current, pageSize, disabled, nameMatch, codeMatch);
    }

    @PostMapping("/category")
    @ServerErrorCatch
    @StrNotNull
    @RsaDe
    @StrMaxLen
    @IsLoginObj
    public RespResult<Object> addProductCategory(
            @RequestBody
            @StrNotNullObj @RsaDeObj @StrMaxLenObj
            ProductCategoryVo productCategoryVo
    ) {
        // 二级商品分类
        List<ProductCategorySub> subs = productCategoryVo.getSubs();
        // 进行解密、字符串合法判断
        for (ProductCategorySub sub : subs) {
            objUtilWithAspect.objStrNotNull(sub);
            objUtilWithAspect.objRsaDe(sub);
            objUtilWithAspect.objStrMaxLen(sub);
        }
        return adminProductService.addProductCategory(Convert2PoUtil.genProductCategory(productCategoryVo), productCategoryVo.getSubs());
    }

    @PostMapping("/category/sub")
    @ServerErrorCatch
    @StrNotNull
    @RsaDe
    @StrMaxLen
    @IsLoginObj
    public RespResult<Object> addProductCategorySub(
            @RequestBody
            @StrNotNullObj @RsaDeObj @StrMaxLenObj
            ProductCategorySub productCategorySub
    ) {
        return adminProductService.addProductCategorySub(productCategorySub);
    }

    @PutMapping("/category")
    @ServerErrorCatch
    @StrNotNull
    @RsaDe
    @StrMaxLen
    @IsLoginObj
    public RespResult<Object> updateProductCategory(
            @RequestBody
            @StrNotNullObj @RsaDeObj @StrMaxLenObj
            ProductCategory productCategory
    ) {
        return adminProductService.updateProductCategory(productCategory);
    }

    @PutMapping("/category/sub")
    @ServerErrorCatch
    @StrNotNull
    @RsaDe
    @StrMaxLen
    @IsLoginObj
    public RespResult<Object> updateProductCategorySub(
            @RequestBody
            @StrNotNullObj @RsaDeObj @StrMaxLenObj
            ProductCategorySub productCategorySub
    ) {
        return adminProductService.updateProductCategorySub(productCategorySub);
    }

    @DeleteMapping("/category")
    @ServerErrorCatch
    @StrNotNull
    @RsaDe
    @IsLoginParam
    public RespResult<Object> delProductCategory(
            @RequestParam(AccountConst.ACCOUNT_PARAM_NAME)
            @StrNotNullParam @RsaDeParam
            String account,
            @RequestParam("id") @NotNullParam
            Long id,
            @RequestParam("toId") @NotNullParam
            Long toId
    ) {
        return adminProductService.deleteProductCategory(id, toId);
    }

    @DeleteMapping("/category/sub")
    @ServerErrorCatch
    @StrNotNull
    @RsaDe
    @IsLoginParam
    public RespResult<Object> delProductCategorySub(
            @RequestParam(AccountConst.ACCOUNT_PARAM_NAME)
            @StrNotNullParam @RsaDeParam
            String account,
            @RequestParam("id") @NotNullParam
            Long id,
            @RequestParam("toId") @NotNullParam
            Long toId,
            @RequestParam("toSubId") @NotNullParam
            Long toSubId
    ) {
        return adminProductService.deleteProductCategorySub(id, toId, toSubId);
    }

    @PostMapping("/upload")
    @ServerErrorCatch
    @NotNull
    @StrNotNull
    @RsaDe
    @StrMaxLen
    @IsLoginObj
    public RespResult<Object> uploadProduct(
            @RequestBody
            @NotNullObj @StrNotNullObj @RsaDeObj @StrMaxLenObj
            UploadProductVo uploadProductVo
    ) {
        for (ProductOptions option : uploadProductVo.getOptions()) {
            objUtilWithAspect.objStrNotNull(option);
            objUtilWithAspect.objRsaDe(option);
            objUtilWithAspect.objStrMaxLen(option);
        }
        for (ProductParam param : uploadProductVo.getParams()) {
            objUtilWithAspect.objStrNotNull(param);
            objUtilWithAspect.objRsaDe(param);
            objUtilWithAspect.objStrMaxLen(param);
        }
        uploadProductVo.setImgList(DecryptUtil.strListRsaDe(uploadProductVo.getImgList(), rsaKeyPair.getPrivateKey()));
        uploadProductVo.setLabelNames(DecryptUtil.strListRsaDe(uploadProductVo.getLabelNames(), rsaKeyPair.getPrivateKey()));
        return adminProductService.uploadProduct(uploadProductVo);
    }

    @GetMapping("/page")
    @ServerErrorCatch
    @NotNull
    @StrNotNull
    @RsaDe
    @StrMaxLen
    @DesEn
    public RespResult<Object> getProductPage(
            @RequestParam(EncryptConstant.DES_KEY_PARAM_NAME)
            @StrNotNullParam @RsaDeParam
            String desKey,
            @NotNullObj @StrNotNullObj @RsaDeObj @StrMaxLenObj
            ProductConditionVo productConditionVo
    ) {
        return adminProductService.getProductPage(productConditionVo);
    }

    @DeleteMapping("/{productId}/logic")
    @ServerErrorCatch
    @NotNull
    @StrNotNull
    @RsaDe
    public RespResult<Object> delProductLogic(
            @RequestParam(AccountConst.ACCOUNT_PARAM_NAME)
            @StrNotNullParam @RsaDeParam
            String account,
            @PathVariable("productId") @NotNullParam
            Long productId
    ) {
        return adminProductService.removeParamByProductIdLogic(productId);
    }

    @PostMapping("/update")
    @ServerErrorCatch
    @NotNull
    @StrNotNull
    @RsaDe
    @StrMaxLen
    @IsLoginObj
    public RespResult<Object> updateProduct(
            @RequestBody
            @NotNullObj @StrNotNullObj @RsaDeObj @StrMaxLenObj
            UploadProductVo uploadProductVo
    ) {
        for (ProductOptions option : uploadProductVo.getOptions()) {
            objUtilWithAspect.objStrNotNull(option);
            objUtilWithAspect.objRsaDe(option);
            objUtilWithAspect.objStrMaxLen(option);
        }
        for (ProductParam param : uploadProductVo.getParams()) {
            objUtilWithAspect.objStrNotNull(param);
            objUtilWithAspect.objRsaDe(param);
            objUtilWithAspect.objStrMaxLen(param);
        }
        uploadProductVo.setImgList(DecryptUtil.strListRsaDe(uploadProductVo.getImgList(), rsaKeyPair.getPrivateKey()));
        uploadProductVo.setLabelNames(DecryptUtil.strListRsaDe(uploadProductVo.getLabelNames(), rsaKeyPair.getPrivateKey()));
        return adminProductService.uploadProduct(uploadProductVo);
    }

    @Autowired
    private CommentsServiceImpl commentsService;

    @GetMapping("/comment")
    @ServerErrorCatch
    @StrNotNull
    @NotNull
    @RsaDe
    @DesEn
    public RespResult<Object> getComment(
            @RequestParam(EncryptConstant.DES_KEY_PARAM_NAME)
            @StrNotNullParam @RsaDeParam
            String desKey,
            @RequestParam(value = "productId", required = false)
            Long productId,
            @RequestParam(value = "userId", required = false)
            Long userId
    ) {
        List<CommentsVo> comments = commentsService.getComments(productId, userId, null);
        return RespResult.success("获取商品评论列表成功", comments);
    }

    @PostMapping("/comment/del")
    @ServerErrorCatch
    @StrNotNull
    @NotNull
    @RsaDe
    @IsLoginParam
    public RespResult<Object> delComment(
            @RequestParam(AccountConst.ACCOUNT_PARAM_NAME)
            @StrNotNullParam @RsaDeParam
            String account,
            @RequestParam(value = "commentId", required = false)
            Long commentId
    ) {
        Boolean res = commentsService.delComment(commentId);
        if (!res) return RespResult.success("获取商品评论删除失败");
        return RespResult.success("获取商品评论删除成功");
    }

}
